<template>
  <div class="complete-sidebar">
    <!-- 第一行：空间下拉列表 + 新增文档按钮 -->
    <div class="toolbar-row">
      <el-dropdown trigger="click" @command="handleSpaceSelect">
        <span class="el-dropdown-link">
          <div class="selected-space-content">
            <span>{{ selectedSpace?.name || '选择空间' }}</span>
            <el-tag v-if="selectedSpace?.permission === 0" type="danger" size="small" class="private-tag">私</el-tag>
          </div>
          <el-icon class="el-icon--right"><arrow-down/></el-icon>
        </span>

        <template #dropdown>
          <el-dropdown-menu>
            <el-dropdown-item v-for="space in spaces" :key="space.id" :command="space.id" class="space-item">
              <div class="space-item-content">
                <div class="space-name-wrapper">
                  <span class="space-name">{{ space.name }}</span>

                  <el-tag v-if="space.permission === 0" type="danger" size="small">私</el-tag>
                </div>

                <div class="space-actions" @click.stop>
                  <el-button type="text" :icon="Edit" size="small" @click="handleEditSpace(space)" title="编辑空间"/>

                  <el-button type="text" :icon="Delete" size="small" @click="handleDeleteSpace(space)"
                             title="删除空间"/>
                </div>
              </div>
            </el-dropdown-item>

            <el-dropdown-item divided command="create-space" style="color: rgb(66, 185, 131);">创建新空间
            </el-dropdown-item>
          </el-dropdown-menu>
        </template>
      </el-dropdown>

      <el-button type="primary" @click="handleCreateDocument">新增</el-button>
    </div>

    <!-- 第二行：搜索框 -->
    <div class="search-row">
      <el-input
          v-model="searchQuery"
          placeholder="搜索"
          :prefix-icon="Search"
          clearable
          @input="handleSearch"
          class="doc-search"/>
    </div>

    <!-- 第三行：文档列表树 -->
    <div class="doc-list" v-if="currentSpaceId">
      <div v-if="loading" class="loading">
        <p>正在加载...</p>
      </div>

      <div v-else-if="filteredTree.length === 0" class="empty-state">
        <p>暂无文档</p>
        <p v-if="currentSpaceId">此空间还没有文档，请创建一个文档</p>
        <p v-else>请先选择一个空间查看文档</p>
      </div>

      <div v-else class="tree-container">
        <el-tree
            class="doc-tree"
            ref="treeRef"
            :data="filteredTree"
            node-key="id"
            :props="treeProps"
            :expand-on-click-node="false"
            :highlight-current="true"
            :current-node-key="selectedDocumentId"
            :default-expanded-keys="defaultExpandKeys"
            draggable
            @node-click="onNodeClick"
            @node-drop="handleNodeDrop"
        >
          <template #default="{ node, data }">
            <div class="tree-node-content">
              <div class="node-label-wrapper">
                <span class="node-label">{{ node.label }}</span>
                <el-tag v-if="data.permission === 1 || data.permission === '1'" type="danger" size="small"
                        class="doc-private-tag">私
                </el-tag>
              </div>
              <div class="node-actions" @click.stop>
                <button @click.stop="onDocumentEdit(data)" class="action-btn edit-btn" title="编辑">
                  ✏️
                </button>
                <button @click.stop="confirmDeleteDocument(data.id)" class="action-btn delete-btn" title="删除">
                  🗑️
                </button>
              </div>
            </div>
          </template>
        </el-tree>
      </div>
    </div>

    <!-- 新增/编辑空间对话框 -->
    <el-dialog
        v-model="showSpaceDialog"
        :title="isEditMode ? '编辑文档空间' : '新增文档空间'"
        width="500px"
        @close="closeSpaceDialog"
    >
      <el-form
          :model="spaceFormData"
          :rules="spaceFormRules"
          ref="spaceFormRef"
          label-width="80px"
          @submit.prevent="submitSpaceForm"
      >
        <el-form-item label="空间名称" prop="name">
          <el-input
              v-model="spaceFormData.name"
              placeholder="请输入空间名称"
              clearable
          />
        </el-form-item>

        <el-form-item label="空间描述" prop="description">
          <el-input
              v-model="spaceFormData.description"
              type="textarea"
              placeholder="请输入空间描述（可选）"
              :rows="3"
              clearable
          />
        </el-form-item>

        <el-form-item label="空间颜色" prop="color">
          <el-color-picker
              v-model="spaceFormData.color"
              show-alpha
              :predefine="predefineColors"
          />
        </el-form-item>

        <el-form-item label="权限设置" prop="permission">
          <el-radio-group v-model="spaceFormData.permission">
            <el-radio :value="0" size="large">
              <span>私有</span>
              <el-text type="info" size="small" class="permission-desc">仅创建者可访问</el-text>
            </el-radio>
            <el-radio :value="1" size="large">
              <span>公开</span>
              <el-text type="info" size="small" class="permission-desc">所有用户可访问</el-text>
            </el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="排序" prop="sortNo">
          <el-input-number v-model="spaceFormData.sortNo" placeholder="请输入排序序号"/>
        </el-form-item>
      </el-form>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeSpaceDialog">取消</el-button>
          <el-button
              type="primary"
              :loading="submitting"
              @click="submitSpaceForm"
          >
            {{ isEditMode ? '更新' : '创建' }}
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import {ref, onMounted, computed, watch} from 'vue'
import {useRoute} from 'vue-router'
import {
  ElDropdown,
  ElDropdownMenu,
  ElDropdownItem,
  ElInput,
  ElIcon,
  ElButton,
  ElMessageBox,
  ElTag,
  ElDialog,
  ElForm,
  ElFormItem,
  ElColorPicker,
  ElRadioGroup,
  ElRadio,
  ElText,
  type FormInstance,
  type FormRules,
  type ElTree
} from 'element-plus'
import {ArrowDown, Search, Edit, Delete} from '@element-plus/icons-vue'
import type {Doc as DocumentType} from '@/modules/doc/types/doc.ts'
import type {NameSpace, CreateNameSpaceRequest} from '@/modules/doc/types/namespace.ts'
import {namespaceApi, documentApi, type DragRequest} from '@/modules/doc/api'
import {useDoc, useDocDetail} from '@/modules/doc/composables'
import {toast} from '@/utils/message.ts'
import type Node from 'element-plus/es/components/tree/src/model/node'

interface Props {
  spaces: NameSpace[]
  selectedSpace: NameSpace | null
  currentSpaceId: string | null
  searchQuery: string
}

interface Emits {
  (e: 'space-select', command: string): void

  (e: 'create-space'): void

  (e: 'edit-space', space: NameSpace): void

  (e: 'delete-space', space: NameSpace): void

  (e: 'space-updated'): void

  (e: 'create-document'): void

  (e: 'search', query: string): void

  (e: 'document-select', document: DocumentType | null): void

  (e: 'document-edit', document: DocumentType): void

  (e: 'document-delete', id: string): void

  (e: 'document-create', spaceId?: string): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

const searchQuery = ref(props.searchQuery)

// 使用 composables
const {
  documents,
  loading,
  fetchDocumentsByNamespace
} = useDoc()

// 文档详情 composable
const {fetchDocumentDetail} = useDocDetail()

const selectedDocumentId = ref<string | null>(null)
const treeRef = ref<InstanceType<typeof ElTree>>()
const defaultExpandKeys = ref<string[]>([])
const currentLoadingSpaceId = ref<string | null>(null)

const route = useRoute()

// el-tree 配置
const treeProps = {
  children: 'children',
  label: 'name'
}

// 计算属性
const currentSpaceId = computed(() => props.currentSpaceId)

// 空间对话框相关状态
const showSpaceDialog = ref(false)
const submitting = ref(false)
const isEditMode = ref(false)
const editingSpaceId = ref<string | null>(null)
const spaceFormRef = ref<FormInstance>()
const spaceFormData = ref<CreateNameSpaceRequest>({
  name: '',
  description: '',
  color: '#42b883',
  sortNo: 0,
  permission: 0  // 默认私有
})

// 表单验证规则
const spaceFormRules: FormRules = {
  name: [
    {required: true, message: '请输入空间名称', trigger: 'blur'},
    {min: 1, max: 50, message: '空间名称长度为1-50个字符', trigger: 'blur'}
  ]
}

// 预定义颜色
const predefineColors = [
  '#42b883',
  '#409EFF',
  '#67C23A',
  '#E6A23C',
  '#F56C6C',
  '#909399',
  '#E4E7ED',
  '#606266',
  '#303133'
]

const handleSpaceSelect = (command: string) => {
  if (command === 'create-space') {
    showCreateSpaceDialog()
    return
  }
  emit('space-select', command)
}

const handleCreateDocument = () => {
  emit('create-document')
}

const handleEditSpace = (space: NameSpace) => {
  showEditSpaceDialog(space)
}

// 空间对话框方法
const showCreateSpaceDialog = (): void => {
  isEditMode.value = false
  editingSpaceId.value = null
  spaceFormData.value = {
    name: '',
    description: '',
    color: '#42b883',
    sortNo: 0,
    permission: 0  // 默认私有
  }
  showSpaceDialog.value = true
}

const showEditSpaceDialog = (space: NameSpace): void => {
  isEditMode.value = true
  editingSpaceId.value = space.id
  spaceFormData.value = {
    name: space.name,
    description: space.description || '',
    color: space.color || '#42b883',
    sortNo: space.sortNo || 0,
    permission: space.permission || 0
  }
  showSpaceDialog.value = true
}

const handleDeleteSpace = async (space: NameSpace) => {
  try {
    await ElMessageBox.confirm(
        `确定要删除空间"${space.name}"吗？删除后该空间下的所有文档也将被删除。`,
        '删除空间',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
    )
    emit('delete-space', space)
  } catch {
    // 用户取消删除
  }
}

// 构建树形结构
const buildTree = (docs: DocumentType[]): DocumentType[] => {
  const docMap = new Map<string, DocumentType>()
  const roots: DocumentType[] = []

  // 创建文档映射
  docs.forEach(doc => {
    docMap.set(doc.id, {...doc, children: []})
  })

  // 构建树形结构
  docs.forEach(doc => {
    const docWithChildren = docMap.get(doc.id)!
    if (doc.parentId && docMap.has(doc.parentId)) {
      const parent = docMap.get(doc.parentId)!
      if (!parent.children) parent.children = []
      parent.children.push(docWithChildren)
    } else {
      roots.push(docWithChildren)
    }
  })

  return roots
}

// 过滤树形结构
const filterTree = (tree: DocumentType[], query: string): DocumentType[] => {
  if (!query.trim()) return tree

  const queryLower = query.toLowerCase()

  const filter = (node: DocumentType): DocumentType | null => {
    const matches = node.name.toLowerCase().includes(queryLower) ||
        (node.content && node.content.toLowerCase().includes(queryLower))

    const filteredChildren = (node.children || [])
        .map(child => filter(child))
        .filter(Boolean) as DocumentType[]

    if (matches || filteredChildren.length > 0) {
      return {...node, children: filteredChildren}
    }

    return null
  }

  return tree.map(root => filter(root)).filter(Boolean) as DocumentType[]
}

const documentTree = computed(() => buildTree(documents.value))
const filteredTree = computed(() => filterTree(documentTree.value, searchQuery.value))

// 获取文档列表
const fetchDocuments = async (): Promise<void> => {
  const spaceId = props.currentSpaceId

  if (!spaceId) {
    console.log('[Menu] 没有空间ID，清空文档列表')
    documents.value = []
    currentLoadingSpaceId.value = null
    return
  }

  // 防止重复调用同一个空间
  if (currentLoadingSpaceId.value === spaceId) {
    console.log('[Menu] 空间', spaceId, '正在加载中，跳过重复调用')
    return
  }

  console.log('[Menu] 开始加载空间', spaceId, '的文档列表')
  currentLoadingSpaceId.value = spaceId

  try {
    await fetchDocumentsByNamespace(spaceId, {
      flatten: true, // 设置为true，获取扁平数组，然后由我们的buildTree函数构建树形结构
      sort: true
    })

    // 检查是否在加载过程中空间又变了
    if (props.currentSpaceId !== spaceId) {
      console.log('[Menu] 空间已切换，放弃本次加载结果')
      return
    }

    console.log('[Menu] 空间', spaceId, '文档列表加载完成，共', documents.value.length, '个文档')

    // 设置默认展开的节点和选中状态
    if (documents.value.length > 0) {
      if (route.params.id && typeof route.params.id === 'string') {
        // 如果路由里有文档id，使用路由中的id
        defaultExpandKeys.value = [route.params.id]
        // 如果还没有选中文档，选中路由中的文档
        if (!selectedDocumentId.value) {
          const routeDoc = documents.value.find(doc => doc.id === route.params.id)
          if (routeDoc) {
            selectedDocumentId.value = route.params.id
            await onDocumentSelect(routeDoc)
          }
        }
      } else {
        // 如果没有路由id，使用列表第一个文档的id
        defaultExpandKeys.value = [documents.value[0].id]
        // 如果还没有选中文档，自动选择第一个文档
        if (!selectedDocumentId.value) {
          const firstDoc = documents.value[0]
          selectedDocumentId.value = firstDoc.id
          await onDocumentSelect(firstDoc)
        }
      }
    }

    currentLoadingSpaceId.value = null
    console.log('[Menu] 空间', spaceId, '文档加载流程完成')
  } catch (err: any) {
    console.error('[Menu] 获取文档列表失败:', err)
    currentLoadingSpaceId.value = null

    let errorMessage = ''
    if (err.code === 'ECONNREFUSED' || err.code === 'ERR_NETWORK') {
      errorMessage = '无法连接到服务器，请检查网络连接'
    } else if (err.response?.status === 404) {
      errorMessage = 'API接口未找到，请检查服务器配置'
    } else if (err.response?.status >= 500) {
      errorMessage = '服务器错误，请稍后重试'
    } else {
      errorMessage = `获取文档列表失败: ${err.response?.data?.message || err.message}`
    }

    // 使用toast显示错误，而不是在页面中显示
    toast.error(errorMessage)
  } finally {
    loading.value = false
  }
}

const refreshDocuments = (): void => {
  fetchDocuments()
}

const handleSearch = (query: string) => {
  emit('search', query)
}

const onDocumentSelect = async (document: DocumentType | null): Promise<void> => {
  if (!document) {
    emit('document-select', null)
    return
  }

  selectedDocumentId.value = document.id

  // 总是获取最新的详细信息，确保包含layoutType等完整字段
  try {
    const detailDoc = await fetchDocumentDetail(document.id, {
      showLoading: false,
      showError: false
    })
    const fullDocument: DocumentType = {
      ...document,
      content: detailDoc?.content || document.content,
      sortNo: detailDoc?.sortNo || document.sortNo,
      createdTime: detailDoc?.createdTime || document.createdTime,
      updatedTime: detailDoc?.updatedTime || document.updatedTime,
      items: detailDoc?.items || document.items || [],
      layoutType: detailDoc?.layoutType || document.layoutType
    }
    emit('document-select', fullDocument)
  } catch (error) {
    console.error('获取文档详情失败:', error)
    emit('document-select', document)
  }
}

const onDocumentEdit = (document: DocumentType): void => {
  emit('document-edit', document)
}

// 这些函数已被其他方式直接调用emit替代

const confirmDeleteDocument = async (id: string): Promise<void> => {
  try {
    const confirmed = await toast.confirm(
        '确定要删除这个文档吗？此操作不可撤销。',
        {
          title: '删除文档',
          confirmButtonText: '删除',
          cancelButtonText: '取消'
        }
    )

    if (!confirmed) return

    // 直接调用删除接口
    await documentApi.delete(id)

    // 刷新文档列表
    await fetchDocuments()

    // 通知父组件文档已删除（父组件可能需要清除选中状态等）
    emit('document-delete', id)
  } catch (error) {
    console.error('删除文档失败:', error)
    toast.error('删除文档失败：' + (error as Error).message)
  }
}

// el-tree 节点点击事件
const onNodeClick = (data: DocumentType) => {
  // 设置默认展开的节点为当前点击的节点
  defaultExpandKeys.value = [data.id]
  onDocumentSelect(data)
}

// el-tree 拖拽处理
const handleNodeDrop = async (
    draggingNode: Node,
    dropNode: Node,
    dropType: 'before' | 'after' | 'inner',
    _event: DragEvent
) => {
  try {
    // 获取被拖拽节点的ID
    const dragNodeId = draggingNode.data.id as string

    // 构建拖拽请求
    const dragRequest: DragRequest = {
      targetId: dropNode.data.id,
      dropType: dropType
    }

    // 调用后端接口
    await documentApi.drag(dragNodeId, dragRequest)
  } catch (error) {
    console.error('拖拽失败:', error)
    toast.error('拖拽失败：' + (error as Error).message)
    // 拖拽失败时重新加载文档列表以恢复原状态
    await fetchDocuments()
  }
}

// const handleSpaceUpdated = () => {
//   emit('space-updated')
// }

const closeSpaceDialog = (): void => {
  showSpaceDialog.value = false
  isEditMode.value = false
  editingSpaceId.value = null
  spaceFormData.value = {
    name: '',
    description: '',
    color: '#42b883',
    sortNo: 0,
    permission: 0
  }
  submitting.value = false
  // 重置表单验证状态
  if (spaceFormRef.value) {
    spaceFormRef.value.resetFields()
  }
}

const submitSpaceForm = async (): Promise<void> => {
  // 表单验证
  if (!spaceFormRef.value) return

  try {
    const valid = await spaceFormRef.value.validate()
    if (!valid) return
  } catch {
    return
  }

  submitting.value = true

  try {
    if (isEditMode.value && editingSpaceId.value) {
      // 编辑模式
      await namespaceApi.update(editingSpaceId.value, spaceFormData.value)
      emit('space-updated')
    } else {
      // 新增模式
      await namespaceApi.create(spaceFormData.value)
      toast.success('空间创建成功')
      emit('space-updated')
    }
    closeSpaceDialog()
  } catch (err: any) {
    console.error(isEditMode.value ? '更新空间失败:' : '创建空间失败:', err)
    const errorMsg = getErrorMessage(err)
    toast.error(`${isEditMode.value ? '更新' : '创建'}空间失败: ${errorMsg}`)
  } finally {
    submitting.value = false
  }
}

// 错误消息处理工具函数
const getErrorMessage = (err: any): string => {
  if (err.response?.data?.message) {
    return err.response.data.message
  }

  if (err.response?.status) {
    const statusMap: Record<number, string> = {
      400: '请求参数错误',
      401: '未授权访问',
      403: '权限不足',
      404: '资源不存在',
      409: '数据冲突',
      422: '数据验证失败',
      500: '服务器内部错误',
      502: '网关错误',
      503: '服务暂不可用'
    }

    return statusMap[err.response.status] || `请求失败 (${err.response.status})`
  }

  if (err.code === 'ECONNREFUSED' || err.code === 'ERR_NETWORK') {
    return '网络连接失败'
  }

  if (err.code === 'ENOTFOUND') {
    return 'DNS解析失败'
  }

  if (err.code === 'ETIMEDOUT') {
    return '请求超时'
  }

  return err.message || '未知错误'
}

// 监听props变化
watch(() => props.searchQuery, (newValue) => {
  searchQuery.value = newValue
})

// 监听空间ID变化
watch(() => props.currentSpaceId, (newSpaceId, oldSpaceId) => {
  console.log('[Menu Watch] 空间ID变化:', {oldSpaceId, newSpaceId})

  // 只有当空间真正切换时才清空选中文档，如果是初始化或相同空间则保留
  if (oldSpaceId !== undefined && newSpaceId !== oldSpaceId) {
    console.log('[Menu Watch] 清除旧空间状态')
    // 空间切换时清除所有状态
    selectedDocumentId.value = null
    defaultExpandKeys.value = []
    documents.value = []
    currentLoadingSpaceId.value = null
  }

  if (newSpaceId) {
    console.log('[Menu Watch] 触发 fetchDocuments')
    fetchDocuments()
  }
}, {immediate: false})  // 改为 false，避免初始化时就触发

// 监听路由变化，同步选中的文档ID
watch(() => route.params.id, (newId) => {
  if (newId && typeof newId === 'string') {
    selectedDocumentId.value = newId
  } else if (!newId) {
    selectedDocumentId.value = null
  }
})

// 组件挂载时的初始化
onMounted(() => {
  // 如果有空间ID，获取文档列表
  if (props.currentSpaceId) {
    fetchDocuments()
  }
})

// 暴露方法供父组件调用
defineExpose({
  refreshDocuments,
  selectDocument: (docId: string) => {
    selectedDocumentId.value = docId
  }
})
</script>

<style scoped>
.complete-sidebar {
  width: 100%;
  height: 100%;
  flex-shrink: 0;
  background: #F3F3F3;
  border-right: 1px solid rgba(var(--color-border-light), var(--opacity-border-light));
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding: 0;
}

/* 左侧菜单各行样式 */

.toolbar-row {
  padding: 12px 20px;
  border-bottom: 1px solid #e0e0e0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-shrink: 0;
  background-color: inherit;
}

.search-row {
  padding: 0.5rem 1rem;
  border-bottom: 1px solid #e0e0e0;
  flex-shrink: 0;
  background-color: inherit;
}

.doc-list {
  flex: 1;
  overflow-y: auto;
  padding: 0.5rem 1rem;
  min-height: 0;
}

.user-actions {
  border-top: 1px solid #e0e0e0;
  padding: 16px 20px;
  margin-top: auto;
  flex-shrink: 0;
  background-color: inherit;
}

.action-buttons {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.el-dropdown-link {
  cursor: pointer;
  color: var(--el-color-primary);
  display: flex;
  align-items: center;
}

.selected-space-content {
  display: flex;
  align-items: center;
  gap: 4px;
}

:deep(.el-dropdown-menu__item--divided) {
  border-top-color: #FFFFFF;
}

/* 空间项样式 */
.space-item-content {
  display: flex;
  justify-content: space-between;
  min-width: 200px;
}

.space-name-wrapper {
  display: flex;
  align-items: center;
  gap: 4px;
  flex: 1;
  min-width: 0;
}

.space-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.private-tag {
  flex-shrink: 0;
  font-size: 10px;
  padding: 2px 4px;
  height: auto;
  line-height: 1;
  margin-left: 2px;
}

.space-actions {
  display: flex;
  opacity: 0;
  transition: opacity 0.2s;
}

.space-item:hover .space-actions {
  opacity: 1;
}

.space-actions .el-button {
  padding: 4px;
  min-height: auto;
  width: auto;
}

.space-actions .el-button:hover {
  background-color: var(--el-fill-color-light);
}

/* 对话框footer样式 */
.dialog-footer {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
}

/* 权限描述样式 */
.permission-desc {
  margin-left: 8px;
  display: block;
}

/* 文档列表样式 */
.loading, .empty-state {
  padding: 2rem 1rem;
  text-align: center;
  color: #666;
}

.tree-container {
  flex: 1;
  overflow-y: auto;
  padding: 0.5rem 0;
}

/* el-tree 样式适配 */
.doc-tree {
  background: transparent !important;
  color: inherit;
}

:deep(.doc-tree) {
  background-color: transparent !important;
  --el-bg-color: transparent !important;
}

:deep(.doc-tree .el-tree-node) {
  background-color: transparent !important;
}

:deep(.doc-tree .el-tree-node__content) {
  padding: 0.5rem 1rem;
  border-left: 3px solid transparent;
  transition: all 0.2s;
  background-color: transparent !important;
}

:deep(.doc-tree .el-tree-node__content:hover) {
  background: #f0f9ff;
}

:deep(.doc-tree .el-tree-node.is-current > .el-tree-node__content) {
  background: #e6f7ff;
  color: #42b883;
  font-weight: 500;
}

:deep(.doc-tree .el-tree-node__expand-icon) {
  color: #666;
}

:deep(.doc-tree .el-tree-node__expand-icon:hover) {
  color: #42b883;
}

.tree-node-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}

.node-label-wrapper {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 6px;
  overflow: hidden;
  min-width: 0;
}

.node-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.9rem;
}

.doc-private-tag {
  flex-shrink: 0;
  font-size: 10px;
  padding: 2px 4px;
  height: auto;
  line-height: 1;
}

.node-actions {
  display: flex;
  gap: 0.25rem;
  opacity: 0;
  transition: opacity 0.2s;
}

.tree-node-content:hover .node-actions {
  opacity: 1;
}

.action-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.2rem;
  border-radius: 3px;
  font-size: 0.7rem;
  transition: all 0.2s;
}

.action-btn:hover {
  background: rgba(66, 184, 131, 0.1);
}

.edit-btn:hover {
  background: rgba(116, 185, 255, 0.2);
}

.delete-btn:hover {
  background: rgba(253, 121, 168, 0.2);
}

/* 深色模式适配 */
.dark .complete-sidebar {
  background: #252525;
  border-right-color: rgba(var(--color-border-dark), var(--opacity-border-dark));
}

.dark .toolbar-row {
  border-bottom-color: #3a3a3a;
}

.dark .search-row {
  border-bottom-color: #3a3a3a;
}

.dark .user-actions {
  border-top-color: #3a3a3a;
}

.dark .doc-list {
  background: transparent !important;
}

.dark .tree-container {
  background: transparent !important;
}

.dark .loading, .dark .empty-state {
  color: #b3b3b3;
}

/* 深色主题下的 el-tree 样式 */
.dark .doc-tree {
  background: transparent !important;
  color: #e6e6e6 !important;
}

.dark :deep(.doc-tree) {
  background-color: transparent !important;
  --el-bg-color: transparent !important;
}

.dark :deep(.doc-tree .el-tree-node) {
  background-color: transparent !important;
  color: #e6e6e6 !important;
}

.dark :deep(.doc-tree .el-tree-node__content) {
  color: #e6e6e6 !important;
  background-color: transparent !important;
}

.dark :deep(.doc-tree .el-tree-node__content:hover) {
  background-color: rgba(66, 184, 131, 0.1) !important;
}

.dark :deep(.doc-tree .el-tree-node.is-current > .el-tree-node__content) {
  background-color: rgba(66, 184, 131, 0.2) !important;
  border-left-color: #42b883;
  color: #42b883 !important;
  font-weight: 600;
}

.dark :deep(.doc-tree .el-tree-node__expand-icon) {
  color: #999999 !important;
}

.dark :deep(.doc-tree .el-tree-node__expand-icon:hover) {
  color: #42b883 !important;
}

.dark :deep(.doc-tree .el-tree-node__label) {
  color: #e6e6e6 !important;
}

.dark :deep(.el-tree) {
  background-color: transparent !important;
  --el-bg-color: transparent !important;
}

.dark :deep(.el-tree__empty-block) {
  background-color: transparent !important;
  color: #999999 !important;
}

.dark :deep(.el-tree__empty-text) {
  color: #999999 !important;
}

.dark :deep(.el-tree__drop-indicator) {
  background-color: #42b883 !important;
}

.dark .node-label {
  color: #e6e6e6;
}

.dark .action-btn {
  color: #b3b3b3;
}

.dark .action-btn:hover {
  color: #e6e6e6;
}

.dark .edit-btn:hover {
  background: rgba(116, 185, 255, 0.15);
}

.dark .delete-btn:hover {
  background: rgba(253, 121, 168, 0.15);
}

@media (max-width: 768px) {
  .header-controls {
    flex-direction: column;
    align-items: stretch;
    gap: 0.75rem;
  }

  .search-input {
    width: 100%;
  }

  .action-buttons {
    justify-content: center;
  }
}
</style>